package Controladores;

import java.awt.Point;
import java.awt.geom.Area;
import java.util.Vector;

import Balas.Bala;
import Juego.Juego;
import PowerUps.PowerUp;

/**Clase que controla el movimiento de las balas, inserciones, eliminaciones e impactos, ademas controla los powerUps
 * 
 * @author Javier Graff
 * @author Eric Avondet
 * @author Rodrigo Herrera
 *
 */
public class Control_Balas  implements Runnable
{
	
	protected Juego juego;
	private Vector<Bala> balas;
	private Vector<Bala> balas_a_agregar;
	private Vector<Bala> balasborrar;
	protected Vector<PowerUp> powerUps;
	protected Vector<PowerUp> powerUps_add;
	protected Vector<PowerUp> powerUps_delete;
	protected boolean terminarhilo;
	protected boolean pausa_movimiento;


	/**Constructor, inicializa atributos
	 * 
	 * @param j juego
	 */
	public Control_Balas(Juego j)
	{
		terminarhilo=false;
		juego=j;
		balas = new Vector<Bala>();
		balasborrar = new Vector<Bala>();
		balas_a_agregar = new Vector<Bala>();
		powerUps = new Vector<PowerUp>();
		powerUps_delete = new Vector<PowerUp>();
		powerUps_add = new Vector<PowerUp>();
		pausa_movimiento=false;
	}
	
	/**
	 * pausa el movimiento de las balas
	 */
	public void pausa()
	{
		pausa_movimiento=true;
	}
	
	/**
	 * continua con el movimiento de las balas
	 */
	public void fin_pausa()
	{
		pausa_movimiento=false;
	}
	
	
	
	/**agrega un powerUp
	 * 
	 * @param p powerUp
	 */
	public void agregar_powerUp(PowerUp p)
	{
		powerUps_add.add(p);
	}
	
	/**elimina un powerUp
	 * 
	 * @param p powerUp
	 */
	public void eliminar_powerUp(PowerUp p)
	{
		powerUps_delete.add(p);
	}
	
	/**
	 * remueve los powerUps que se han indicado como removibles
	 */
	public void remover_pwps()
	{
		for (int i=0; i<powerUps_delete.size();i++)
		{
			juego.getgraficos().getGraficoEntidades().getpanel().remove(powerUps_delete.elementAt(i));
			juego.getgraficos().getGraficoEntidades().getpanel().repaint();
			powerUps.remove(powerUps_delete.elementAt(i));
		}
		powerUps_delete.removeAllElements();
	}
	
	/**
	 * agrega los powerUps que se han indicado como agregables
	 */
	public void agregar_pwps()
	{
		for (int i=0; i<powerUps_add.size();i++)
		{
			powerUps.add(powerUps_add.elementAt(i));
		}
		powerUps_add.removeAllElements();
	}
	
	/**indica que una bala debe ser agregada
	 * 
	 * @param b bala a agregar
	 */
	public void agregar_bala(Bala b)
	{
		balas_a_agregar.add(b);
	}
	
	/**indica que una bala debe ser eliminada
	 * 
	 * @param b bala a borrar
	 */
	public void bala_a_borrar(Bala b)
	{
		balasborrar.add(b);
	}
	
	/**
	 * detecta si la bala supero el rango de la pantalla
	 * @param b bala
	 * @return true si supero falso caso contrario
	 */
	public boolean bala_fueraDeRango(Bala b)
	{
		Point p = b.getLocation();
		boolean bfr=false;
		
		if ( 	
				(p.getY()-20<0) 
				|| (p.getY()>juego.getgraficos().getGraficoEntidades().getpanel().getHeight() )
				|| ((p.getX() + b.getWidth())<0) 
				|| (p.getX()>juego.getgraficos().getGraficoEntidades().getpanel().getWidth())   
			)
			bfr = true;
		
		return bfr;
	}
	
	/**
	 * controla la interseccion entre los powerUps  y una bala
	 * @param b bala
	 * @return true si se intersecta la bala con algun powerUp
	 */
	public boolean intersectar_powerUp(Bala b)
	{
		Area areabala = new Area(b.getBounds());
		for (int i=0; i< powerUps.size();i++)
		{
			Area areapwp = new Area(powerUps.elementAt(i).getBounds());
			if (areapwp.intersects(areabala.getBounds2D()))
			{
				b.impactar(powerUps.elementAt(i));
				return true;
			}
		}
		return false;
	}
	

	/**
	 * contorla si la bala se intersecta con el tanque del jugador
	 * @param b bala
	 * @return true si chocan
	 */
	public boolean intersectar_tanque(Bala b)
	{
		Area areatanque = new Area(juego.getTanque().getBounds());
		Area areabala = new Area(b.getBounds());
		if (areatanque.intersects(areabala.getBounds2D()))
			{
				b.impactar(juego.getTanque());
				return true;
			}
		return false;
	}
	
	/**
	 * Movimiento de las balas por pantalla, controla colisiones
	 */
	public void movimiento()
	{
		boolean chocoTanque=false;

			for (int i=0; i< balas.size(); i++)
			{
				balas.elementAt(i).mover();
				
				if (!this.intersectar_powerUp(balas.elementAt(i)))
				{
				
						if (bala_fueraDeRango(balas.elementAt(i)) )    
						{	
							bala_a_borrar(balas.elementAt(i));
							//borre=true;
						}	
						else
						{
							chocoTanque = intersectar_tanque(balas.elementAt(i));
						}
						if (!chocoTanque)
						{
							 juego.getcontrolenemigos().controlbalas(balas.elementAt(i));
						}

				}
				

			}
			
			for (int i=0;i<powerUps.size();i++)
				intersec_pwp_tanque(powerUps.elementAt(i));
			
			remover_pwps();
			agregar_pwps();
			borrar_borrables();
			agregar_agregables();
			
		
		
		
		
		
	}
	
	/**
	 * controla la interseccion de un powerUp con el tanque
	 * @param p powerUp
	 */
	private void intersec_pwp_tanque(PowerUp p) 
	{
		Area areatanque = new Area(juego.getTanque().getBounds());
		Area areapwp = new Area(p.getBounds());
		if (areatanque.intersects(areapwp.getBounds2D()))
			{
				p.tocar_tanque(juego.getTanque());	
			}
	}




	/**
	 * Agrega las balas que deben ser agregadas
	 */
	public void agregar_agregables()
	{
		//agrego las que se deben agregar
			for (int i=0; i< balas_a_agregar.size();i++)
			{
				balas.add(balas_a_agregar.elementAt(i));
			}
			balas_a_agregar.removeAllElements();
	}
	
	/**
	 * Elimina las balas que deben ser eliminadas
	 */
	public void borrar_borrables()
	{
		//borra las balas que desaparecen
			for(int i=0; i< balasborrar.size(); i++)
			{
				juego.getgraficos().getGraficoEntidades().getpanel().remove(balasborrar.elementAt(i));
				juego.getgraficos().getGraficoEntidades().getpanel().repaint();
				balas.remove(balasborrar.elementAt(i));
			}
			balasborrar.removeAllElements();
	}
	
	/**
	 * Finaliza el hilo
	 */
	public void terminar_hilo()
	{
		terminarhilo=true;
	}

	@Override
	public void run() 
	{
		while (!terminarhilo)
		{
			if (!pausa_movimiento)
					this.movimiento();
			
			try {
				Thread.sleep(40);
			} catch (InterruptedException e) {

				e.printStackTrace();
			}
			// TODO Auto-generated method stub
		}
	}
	
	

}
